package com.cyw.common.config.redis;

import com.cyw.common.config.jackson.JacksonConfig;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

@Configuration
@Import({ RedisManager.class})
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableConfigurationProperties(RedisKeyPrefixProperties.class)
@SuppressWarnings("all")
public class RedisTemplateConfig {

    @Resource
    private RedisKeyPrefixProperties redisKeyPrefixProperties;

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new PrefixStringKeySerializer(redisKeyPrefixProperties));
        template.setValueSerializer(new StringRedisSerializer(StandardCharsets.UTF_8));
        return template;
    }

    @Bean
    public <V> RedisTemplate<String, V> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, V> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new PrefixStringKeySerializer(redisKeyPrefixProperties));
        redisTemplate.setHashKeySerializer(new PrefixStringKeySerializer(redisKeyPrefixProperties));

        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }

    @Bean
    public <V> ValueOperations<String, V> valueOperations(RedisTemplate<String, V> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    @Bean
    public <V> ListOperations<String, V> listOperations(RedisTemplate<String, V> redisTemplate) {
        return redisTemplate.opsForList();
    }

    @Bean
    public <V> SetOperations<String, V> setOperations(RedisTemplate<String, V> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    @Bean
    public <V> HashOperations<String, String, V> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    @Bean
    public <V> ZSetOperations<String, V> zSetOperations(RedisTemplate<String, V> redisTemplate) {
        return redisTemplate.opsForZSet();
    }


    public static ObjectMapper objectMapper() {
        ObjectMapper objectMapper = JacksonConfig.getObjectMapperWithoutIdModule();
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return objectMapper;
    }

}
